package fr.ups.jim.isi.tp4 ;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame ;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

import java.awt.Component ;
import java.awt.Container ;
import java.awt.FlowLayout;
import java.awt.Graphics2D ;
import java.awt.Graphics ;
import java.awt.Dimension ;
import java.awt.Color ;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle ;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter ;
import java.awt.event.MouseMotionAdapter ;
import java.awt.event.MouseEvent ;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Ji MA (ji.ma@u-psud.fr)
 *
 */
public class MyGraphicalEditor extends JFrame {
	
	private static final long serialVersionUID = 1L;
	private PersistentCanvas canvas;
	private String mode;
	private CanvasItem item;
	private CanvasItem selectedItem;
	private ArrayList<JButton> operationButtons;
	private ArrayList<JPanel> colorChooser;
	private Point mousePos;
	
	private MouseAdapter canvasMouseListener = new MouseAdapter() {
		public void mousePressed(MouseEvent e) {
			mousePos = e.getPoint();
			
			if (mode.equals("Select/Move")) {	
				if (selectedItem != null)
					selectedItem.deselected();
				selectedItem = canvas.getItemContainsPoint(mousePos);
				if (selectedItem != null) {
					for (JButton button : operationButtons)
						button.setEnabled(true);
					selectedItem.selected();
				}
				else if (selectedItem == null) {
					for (JButton button : operationButtons)
						button.setEnabled(false);
				}
			}
			else {
				
				if (mode.equals("Rectangle")) {
					item = new RectangleItem(canvas, 
							colorChooser.get(0).getBackground(), 
							colorChooser.get(1).getBackground(),
							e.getPoint());
				}
				else if (mode.equals("Ellipse")) {
					item = new EllipseItem(canvas, 
							colorChooser.get(0).getBackground(), 
							colorChooser.get(1).getBackground(),
							e.getPoint());
				}
				else if (mode.equals("Line")) {
					item = new LineItem(canvas, 
							colorChooser.get(0).getBackground(), 
							colorChooser.get(1).getBackground(),
							e.getPoint());
				}
				else if (mode.equals("Path")) {
					item = new PathItem(canvas, 
							colorChooser.get(0).getBackground(), 
							Color.WHITE,
							e.getPoint());
				}
				
				// ensure the newly drawn shape is always active
				if (selectedItem != null) {
					selectedItem.deselected();
				}
				selectedItem = item;
				selectedItem.selected();
				
				canvas.itemsList.add(item);
			}
			 
		}	
		
		public void mouseReleased(MouseEvent e) {
			item = null;
		}
		
		public void mouseClicked(MouseEvent e) {
			mousePos = e.getPoint();
			
			if (mode.equals("Select/Move")) {
				
				if (selectedItem != null)
					selectedItem.deselected();
				/* calculate which shape item is selected */
				selectedItem = canvas.getItemContainsPoint(mousePos);
				if (selectedItem != null) {
					for (JButton button : operationButtons)
						button.setEnabled(true);
					selectedItem.selected();
				}
				else if (selectedItem == null) {
					for (JButton button : operationButtons)
						button.setEnabled(false);
				}
			}		
		}	
	};
	
	private MouseMotionAdapter canvasMouseMotionListener = new 
			MouseMotionAdapter() {
		
		public void mouseDragged(MouseEvent e) {
			
			if (mode.equals("Select/Move")) {
				if (selectedItem != null) {
					selectedItem.move(e.getX() - mousePos.x, 
							e.getY() - mousePos.y);
				}
			}
			else {
				if (item == null) 
					return ;
				else
					item.update(e.getPoint());
			}
			
			mousePos = e.getPoint();
		}
	};
	
	
	private MouseAdapter radioButtonListener = new MouseAdapter() {
		public void mouseClicked(MouseEvent e) {
			JRadioButton radioButton = (JRadioButton) e.getSource();
			mode = radioButton.getText();
			updateTitle(radioButton.getText());
		}
	};
	
	private MouseAdapter colorChooserListener = new MouseAdapter() {
		public void mouseClicked(MouseEvent e) {
			JPanel jp = (JPanel) e.getSource();
			
			Color c;
			if (jp.getName().equals("outline")) {
				c = JColorChooser.showDialog(null, "Select the Outline Color"
						, Color.GRAY);
			}
			else {
				c = JColorChooser.showDialog(null, "Select the Fill Color"
						, Color.GRAY);
			}
			
			jp.setBackground(c);
			if (selectedItem != null) {
				if (jp.getName().equals("fill")) {
					selectedItem.setFillColor(c);
				}
				else if (jp.getName().equals("outline")) {
					selectedItem.setOutlineColor(c);
				}
			}
		}
	};
	
	private ActionListener operationListener = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			JButton operation = (JButton) e.getSource();
			
			if (selectedItem == null)
				return;
			else {
				
				if (operation.getText().equals("Clone")) {
					selectedItem.deselected();
					selectedItem = selectedItem.duplicate();
					selectedItem.selected();
				}
				else if (operation.getText().equals("Delete")) {				
					canvas.removeItem(selectedItem);
					int lastItem = canvas.itemsList.size() - 1;
					if (lastItem >= 0) {
						selectedItem = canvas.itemsList.get(lastItem);
						selectedItem.selected();
					}
					else {
						for (JButton button : operationButtons) {
							button.setEnabled(false);
						}
					}

				}
			}
			
		}
	};
	
    public MyGraphicalEditor(String title, int width, int height) {
	   setTitle(title) ;
	   Container pane = getContentPane() ;
	   setLayout(new GridBagLayout());
	   GridBagConstraints globalConstraints = new GridBagConstraints();
	   
	   
	   mode = "Rectangle";
	   // create a menu panel to hold the menu buttons, ratio buttons, etc..
	   JPanel menuPanel = new JPanel();
	   GridBagLayout menuLayout = new GridBagLayout();
	   menuPanel.setLayout(menuLayout);
	   GridBagConstraints localConstraints = new GridBagConstraints();
	   localConstraints.gridwidth = GridBagConstraints.REMAINDER;
	   localConstraints.anchor = GridBagConstraints.WEST;	// align to left
	   
	   // create five JRadioButtons 
	   // associate the five JRadioButtons to a button group
	   // and add them to the menu panel
	   ButtonGroup bg = new ButtonGroup();
	   JRadioButton selectOrMove = customizedRadioButton("Select/Move", bg);
	   JRadioButton rectangle = customizedRadioButton(("Rectangle"), bg);
	   JRadioButton ellipse = customizedRadioButton("Ellipse", bg);
	   JRadioButton line = customizedRadioButton("Line", bg);
	   JRadioButton path = customizedRadioButton("Path", bg);
	   rectangle.setSelected(true);
	   
	   menuPanel.add(selectOrMove, localConstraints);
	   menuPanel.add(rectangle, localConstraints);
	   menuPanel.add(ellipse, localConstraints);
	   menuPanel.add(line, localConstraints);
	   localConstraints.insets = new Insets(0, 0, 50, 0);
	   menuPanel.add(path, localConstraints);
	   
	   // create two JColorChoosers for setting interior color and border color
	   JPanel fillColorChooser = customizedColorPanel("fill");
	   JPanel outlineColorChooser = customizedColorPanel("outline");
	   colorChooser = new ArrayList<JPanel>();
	   colorChooser.add(outlineColorChooser);
	   colorChooser.add(fillColorChooser);
	   
	   localConstraints.insets = new Insets(0, 0, 15, 0);
	   menuPanel.add(fillColorChooser, localConstraints);
	   localConstraints.insets = new Insets(0, 0, 50, 0);
	   menuPanel.add(outlineColorChooser, localConstraints);
	   
	   
	   // create two buttons "Delete" and "Clone" for corresponding operations
	   JButton deleteButton = customizedJButton("Delete");
	   JButton cloneButton = customizedJButton("Clone");
	   operationButtons = new ArrayList<JButton>();
	   operationButtons.add(deleteButton);
	   operationButtons.add(cloneButton);
	   localConstraints.insets = new Insets(0, 0 , 15, 0);
	   localConstraints.anchor = GridBagConstraints.CENTER;
	   menuPanel.add(deleteButton, localConstraints);
	   menuPanel.add(cloneButton, localConstraints);
	   
	   globalConstraints.gridwidth = GridBagConstraints.RELATIVE;
	   pane.add(menuPanel, globalConstraints);
	   
	   
	   // create the drawing board and add it to the main container
	   canvas = new PersistentCanvas() ;
	   canvas.setBackground(Color.WHITE) ;
	   canvas.setPreferredSize(new Dimension(width,height)) ;
	   globalConstraints.gridwidth = GridBagConstraints.REMAINDER;
	   pane.add(canvas, globalConstraints) ;

	   canvas.addMouseListener(canvasMouseListener);
	   canvas.addMouseMotionListener(canvasMouseMotionListener);

	   pack() ;
	   setVisible(true) ;
    }
    
    /**
     * Create a JRadioButton for a given name and binds it to a ButtonGroup
     * @param name	JRadioButton name
     * @param bg	Created JRadioButton will be binded to this ButtonGroup
     * @return		Created JRadioButton
     */
    private JRadioButton customizedRadioButton (String name, ButtonGroup bg) {
    	JRadioButton radioButton = new JRadioButton(name);
    	radioButton.addMouseListener(radioButtonListener);
    	bg.add(radioButton);
    	return radioButton;
    }
    
    /**
     * Create customized Color Chooser Panel, which hides the default color
     * preview panel until user clicks on this panel
     * @return	created JPanel
     */
    private JPanel customizedColorPanel (String s) {
    	JPanel panel = new JPanel();
    	panel.setName(s);
    	panel.setOpaque(true);
    	panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
    	if (s.equals("outline"))
    		panel.setBackground(Color.BLACK);
    	else
    		panel.setBackground(Color.LIGHT_GRAY);
    	panel.setPreferredSize(new Dimension(100, 20));
    	panel.setMaximumSize(new Dimension(100,20));
    	
    	// lauch the default JColorChooser preview panel and set the changed 
    	// color if necessary
    	panel.addMouseListener(colorChooserListener);
    	
    	return panel;	
    }
    
    /**
     * Create a button with user-defined size and bind it with a ActionListener
     * @param buttonName	button name
     * @return				created button
     */
    private JButton customizedJButton (String buttonName) {
    	JButton button = new JButton(buttonName);
    	button.setPreferredSize(new Dimension(75,30));
    	button.setMaximumSize(new Dimension(75, 30));
    	button.addActionListener(operationListener);
    	button.setEnabled(false);
    	return button;
    }
    
    /**
     * Update the title of graphic editor
     * @param newTitle	current mode : "Select/Move", "Rectangle", "Line", etc.
     */ 
    private void updateTitle (String newTitle) {
    	setTitle("Graphic Editor : " + newTitle);
    }
    
    public static void main(String[] args) {
	   MyGraphicalEditor editor = new 
	   		MyGraphicalEditor("Graphic Editor",800,600) ;
	   editor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) ;
    }

}
